package cn.topevery.garden.wapi.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.topevery.garden.dal.logic.BaseInfoLogic;
import cn.topevery.garden.dal.logic.GreFileLogic;
import cn.topevery.garden.dal.logic.GreLandLogic;
import cn.topevery.garden.dal.logic.GreLandRecordLogic;
import cn.topevery.garden.entity.dto.GreLandDTO;
import cn.topevery.garden.entity.po.BaseInfo;
import cn.topevery.garden.entity.po.GreFile;
import cn.topevery.garden.entity.po.GreLand;
import cn.topevery.garden.entity.po.GreLandRecord;
import cn.topevery.garden.entity.query.BaseInfoQuery;
import cn.topevery.garden.entity.query.GreLandQuery;
import cn.topevery.garden.entity.vo.CoveragePercentVO;
import cn.topevery.garden.entity.vo.GreLandInDeptVO;
import cn.topevery.garden.entity.vo.GreLandRecordVO;
import cn.topevery.garden.entity.vo.GreLandVO;
import cn.topevery.garden.wapi.model.GreLandFetch;
import cn.topevery.garden.wapi.utils.ExcelUtils;
import com.github.dozermapper.core.Mapper;
import hw.topevery.basis.dal.logic.SysDeptLogic;
import hw.topevery.basis.entity.po.SysDept;
import hw.topevery.basis.entity.po.SysUser;
import hw.topevery.framework.GeometryHelper;
import hw.topevery.framework.db.entity.DataPager;
import hw.topevery.framework.dto.PointDto;
import hw.topevery.framework.util.ExcelUtil;
import hw.topevery.framework.web.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static cn.topevery.garden.entity.po.GreFile.TYPE_GRE_LAND;
import static cn.topevery.garden.framework.util.CurrentUserUtil.getDept;

/**
 * @author code-generate
 * @date 2022-01-05 11:15
 */
@Api(tags = "绿地管理")
@RestController
@RequestMapping("/greLand")
public class GreLandController extends BaseController {

    @Autowired
    private Mapper mapper;

    @Autowired
    GreLandLogic greLandLogic;

    @Autowired
    GreFileLogic greFileLogic;

    @Autowired
    GreLandRecordLogic greLandRecordLogic;

    @Autowired
    BaseInfoLogic baseInfoLogic;

    @Autowired
    SysDeptLogic sysDeptLogic;


    @PostMapping(value = "/getRecordList")
    @ApiOperation(value = "获取绿地历史信息")
    public JsonResult<DataPager<GreLandRecordVO>> getRecordList(@RequestBody GreLandQuery greLandParam) {
        DataPager<GreLandRecordVO> res = greLandLogic.getRecordList(greLandParam);
        List<GreLandRecordVO> records = res.records;
        if (records != null && !records.isEmpty()) {
            records.stream().peek(temp -> {
                temp.setFileList(greFileLogic.getListByMainRecordId(temp.getId(), TYPE_GRE_LAND));
            }).collect(Collectors.toList());
        }
        return JsonResult.ok(res);
    }

    @PostMapping(value = "/getGreLandInDept")
    @ApiOperation(value = "获取区域面积统计")
    public JsonResult<DataPager<GreLandInDeptVO>> getGreLandInDept(@RequestBody GreLandQuery query) {

        DataPager<GreLandInDeptVO> res = greLandLogic.getGreLandInDept(query);
        return JsonResult.ok(res);
    }

    @ApiOperation(value = "获取页列表")
    @PostMapping("/getList")
    public JsonResult<DataPager<GreLandVO>> listPage(@RequestBody GreLandQuery query) {
        DataPager<GreLandVO> res = greLandLogic.listPage(query);
        List<GreLandVO> records = res.records;
        if (records != null && !records.isEmpty()) {
            records.stream().peek(temp -> {
                temp.setFileList(greFileLogic.getListByMainId(temp.getId(), TYPE_GRE_LAND));
                temp.setMapRangesPoints(GeometryHelper.getGeomePoint(temp.getMapRanges()));
                temp.setMapRanges(null);
            }).collect(Collectors.toList());
        }
        return JsonResult.ok(res);
    }

    @GetMapping(value = "/reback")
    @ApiOperation(value = "绿地信息恢复")
    public JsonResult<?> reback(Integer id) {
        SysUser user = getUser();
        GreLandRecord greLandRecord = greLandRecordLogic.getEntity(id);
        greLandRecord.setId(greLandRecord.getLandIntId());
        GreLandVO greLandVo = new GreLandVO();
        BeanUtils.copyProperties(greLandRecord, greLandVo);
        greLandVo.setFileList(greFileLogic.getListByMainRecordId(id, TYPE_GRE_LAND));
        greLandLogic.commit(greLandVo, user.id);
        return JsonResult.ok("恢复成功");
    }

    @GetMapping(value = "/getGreLandById")
    @ApiOperation(value = "获取单个绿地信息")
    public JsonResult<GreLandVO> getGreLandById(Integer id) {
        GreLand greLand = greLandLogic.getEntity(id);
        List<GreFile> list = greFileLogic.getListByMainId(greLand.getId(), TYPE_GRE_LAND);
        greLand.setFileList(list);
        GreLandVO greLandVO = new GreLandVO();
        BeanUtil.copyProperties(greLand, greLandVO, "mapRanges");
        if (StringUtils.isNotBlank(greLandVO.getDeptId())) {
            SysDept dept = sysDeptLogic.getEntityByDataId(greLand.getDeptId());
            greLandVO.setDeptName(dept.deptName);
        }
        if (greLand.getMapRanges() != null) {
            greLandVO.setMapRangesPoints(GeometryHelper.getGeometryPoint(greLand.getMapRanges()));
        }
        return JsonResult.ok(greLandVO);
    }

    @PostMapping(value = "/getShortList")
    @ApiOperation(value = "获取简短的绿地信息")
    public JsonResult<List<Map<String, Object>>> getShortList(@RequestBody GreLandQuery greLandParam) {
        SysDept dept = getDept();
        SysUser user = getUser();
        String deptId = "";
        if (user.userIsAdmin != 1) {
            deptId = dept.deptId;
        }
        List<Map<String, Object>> res = greLandLogic.getShortList(deptId);
        return JsonResult.ok(res);
    }

    @PostMapping(value = "/commit")
    @ApiOperation(value = "绿地信息新增和修改接口")
    public JsonResult<?> insert(@RequestBody GreLandVO vo) {
        SysUser user = getUser();
        if (!StringUtils.isNotBlank(vo.getCode())) {
            vo.setCode(vo.getGreeClass());
        }
        greLandLogic.commit(vo, user.id);
        return JsonResult.ok("新增成功");
    }

    @PostMapping(value = "dataPublic")
    @ApiOperation(value = "数据发布")
    public JsonResult dataPublic(Integer id, Boolean dataPublic) {
        SysUser user = getUser();
        GreLandVO greLandVO = greLandLogic.getGreLandById(id);
        greLandVO.setMapRangesPoints(GeometryHelper.getGeomePoint(greLandVO.getMapRanges()));
        greLandVO.setDataPublic(dataPublic);
        greLandLogic.commit(greLandVO, user.id);
        return JsonResult.ok();
    }

    @PostMapping(value = "dataPublics")
    @ApiOperation(value = "数据发布")
    public JsonResult dataPublics(@RequestBody List<Integer> ids) {
        SysUser user = getUser();
        ids.forEach(id -> {
            GreLandVO greLandVO = greLandLogic.getGreLandById(id);
            greLandVO.setMapRangesPoints(GeometryHelper.getGeomePoint(greLandVO.getMapRanges()));
            greLandVO.setDataPublic(true);
            greLandLogic.commit(greLandVO, user.id);
        });
        return JsonResult.ok();
    }

    @ApiOperation("新增/编辑 信息")
    @PostMapping("/saveOrUpdate")
    public JsonResult<Boolean> saveOrUpdate(@Valid @RequestBody GreLandDTO dto) {
        if (StringUtils.isNotBlank(dto.getCode())) {
            dto.setCode(dto.getGreeClass());
        }
        greLandLogic.saveOrUpdate(getUser().id.toString(), mapper.map(dto, GreLand.class));
        return JsonResult.ok(true);
    }

    @ApiOperation("通过Id获取详情")
    @GetMapping("/getInfoById")
    public JsonResult<GreLandVO> getInfoById(@RequestParam Integer id) {
        GreLand entity = greLandLogic.getEntity(id);
        GreLandVO vo = mapper.map(entity, GreLandVO.class);
        return JsonResult.ok(vo);
    }

    @ApiOperation("根据自增ID批量删除")
    @PostMapping("/deleteBatchById")
    public JsonResult<Boolean> deleteBatchById(@RequestBody Integer[] ids) {
        greLandLogic.deleteBatchById(getUser().id.toString(), ids);
        return JsonResult.ok(true);
    }

    @GetMapping(value = "/delete")
    @ApiOperation(value = "批量删除")
    public JsonResult<?> delete(String ids) {
        String[] idArray = ids.split(",");
        List<String> idList = Arrays.asList(idArray);
        idList.forEach(id -> {
            GreLand greLand = new GreLand();
            greLand.setDbStatus(false);
            greLand.setId(Integer.parseInt(id));
            greLandLogic.saveOrUpdate(getUser().id.toString(), greLand);
        });

        return JsonResult.ok("删除成功");
    }

    @GetMapping("del")
    @ApiOperation(value = "删除")
    public JsonResult del(Integer id) {
        GreLand greLand = new GreLand();
        greLand.setDbStatus(false);
        greLand.setId(id);
        greLandLogic.saveOrUpdate(getUser().id.toString(), greLand);
        return JsonResult.ok();
    }

    @PostMapping("/analysisExcel")
    @ApiOperation(value = "解析Excel")
    public JsonResult analysisExcelData(@RequestParam("file") MultipartFile file) {
        return greLandLogic.analysisExcel(file);
    }

    @PostMapping(value = "/importExcel")
    @ApiOperation(value = "导入Excel")
    public JsonResult importExcel(@RequestBody List<GreLandVO> greLandVOList) {
        return greLandLogic.importExcel(greLandVOList);
    }

    @ApiOperation("导出信息")
    @GetMapping("/export")
    public void export(GreLandQuery query, HttpServletResponse response) {
        List<GreLandVO> list = greLandLogic.listPage(query).records;
        ExcelUtil.exportExcel(list, "", "sheet1", GreLandVO.class, "", response);
    }

    @GetMapping(value = "/getCoveragePercent")
    @ApiOperation(value = "绿地覆盖率")
    public JsonResult<List<Map<String, Object>>> getCityAreaCoveragePercent(String type, String date, String mapId) {
        LocalDate today = LocalDate.now();
        LocalDate beginDate = null;
        LocalDate endDate = null;
        if (StringUtils.isNotBlank(date)) {
            endDate = LocalDate.parse(date);
        } else {
            switch (type) {
                case "1":
                    beginDate = today.minusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
                    endDate = today.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                    break;
                case "2":
                    int month = today.getMonthValue();
                    int flag = month % 3;
                    beginDate = today.minusMonths(flag + 3).with(TemporalAdjusters.firstDayOfMonth());
                    endDate = today.minusMonths(flag).with(TemporalAdjusters.lastDayOfMonth());
                    break;
                case "3":
                    beginDate = today.with(TemporalAdjusters.firstDayOfYear());
                    endDate = today.with(TemporalAdjusters.firstDayOfYear()).plusMonths(5)
                            .with(TemporalAdjusters.lastDayOfMonth());
                    break;
                case "4":
                    beginDate = today.with(TemporalAdjusters.firstDayOfYear());
                    endDate = today.with(TemporalAdjusters.lastDayOfYear());
                    break;
                default:
            }
        }
        List<Map<String, Object>> list = greLandLogic.getCityAreaCoveragePercent(beginDate, endDate, mapId);
        return JsonResult.ok(list);
    }

    @GetMapping(value = "/getCoveragePercentShow")
    @ApiOperation(value = "绿地覆盖率")
    public JsonResult<List<Map<String, Object>>> getCityAreaCoveragePercentShow(String mapId) {
        BaseInfoQuery query = new BaseInfoQuery();
        query.setPageIndex(1);
        query.setPageSize(10);
        DataPager<BaseInfo> list = baseInfoLogic.getPage(query);
        List<Map<String, Object>> result = new ArrayList<>();
        if (list.records != null && !list.records.isEmpty()) {
            BaseInfo baseInfo = list.records.stream().filter(item -> item.getMapId().equals(mapId)).collect(Collectors.toList()).get(0);
            Map<String, Object> map = new HashMap<String, Object>() {
                {
                    put("greType", "公园绿地");
                    put("sumArea", baseInfo.getGardenMeasure());
                    put("sumGreArea", baseInfo.getGardenGreMeasure());
                    put("percent", baseInfo.getGardenMeasure() == null ? 0 : (baseInfo.getGardenMeasure() / baseInfo.getMeasure()) * 100);
                }
            };
            result.add(map);
            map = new HashMap<String, Object>() {
                {
                    put("greType", "区域绿地");
                    put("sumArea", baseInfo.getAreaMeasure());
                    put("sumGreArea", baseInfo.getAreaGreMeasure());
                    put("percent", baseInfo.getAreaMeasure() == null ? 0 : (baseInfo.getAreaMeasure() / baseInfo.getMeasure()) * 100);
                }
            };
            result.add(map);
            map = new HashMap<String, Object>() {
                {
                    put("greType", "广场绿地");
                    put("sumArea", baseInfo.getGroundMeasure());
                    put("sumGreArea", baseInfo.getGroundGreMeasure());
                    put("percent", baseInfo.getGroundMeasure() == null ? 0 : (baseInfo.getGroundMeasure() / baseInfo.getMeasure()) * 100);
                }
            };
            result.add(map);
            map = new HashMap<String, Object>() {
                {
                    put("greType", "防护绿地");
                    put("sumArea", baseInfo.getProtectLandMeasure());
                    put("sumGreArea", baseInfo.getProtectGreMeasure());
                    put("percent", baseInfo.getProtectLandMeasure() == null ? 0 : (baseInfo.getProtectLandMeasure() / baseInfo.getMeasure()) * 100);
                }
            };
            result.add(map);
            map = new HashMap<String, Object>() {
                {
                    put("greType", "附属绿地");
                    put("sumArea", baseInfo.getAffiliatedMeasure());
                    put("sumGreArea", baseInfo.getAffiliatedGreMeasure());
                    put("percent", baseInfo.getAffiliatedMeasure() == null ? 0 : (baseInfo.getAffiliatedMeasure() / baseInfo.getMeasure()) * 100);
                }
            };
            result.add(map);
        }
        return JsonResult.ok(result);
    }

    @GetMapping(value = "/getCoveragePercentByDate")
    @ApiOperation(value = "获取三年的绿地覆盖率")
    public JsonResult<List<List<CoveragePercentVO>>> getCoveragePercent() {
        List<CoveragePercentVO> list = greLandLogic.getCoveragePercent();
        Map<String, List<CoveragePercentVO>> map = list.stream().collect(Collectors.groupingBy(CoveragePercentVO::getYear));
        List<List<CoveragePercentVO>> lists = new ArrayList<>(map.values());
        lists.sort(Comparator.comparing(temp -> temp.get(0).getYear()));
        return JsonResult.ok(lists);
    }

    @GetMapping(value = "/getSumAreaCompare")
    @ApiOperation(value = "获取日期时间前城市绿化总覆盖面积信息")
    public JsonResult<Map<String, Object>> getCitySumAreaPercentCompareInfo(String date) {
        Map<String, Object> map = greLandLogic.getCitySumAreaCompareInfoByDate(date);
        return JsonResult.ok(map);
    }

    @GetMapping(value = "/getSituation")
    @ApiOperation(value = "获取绿地概况")
    public JsonResult<Map<String, Object>> getSituation() {
        Map<String, Object> map = greLandLogic.getSituation();
        return JsonResult.ok(map);
    }

    @GetMapping(value = "/getSituationShow")
    @ApiOperation(value = "获取绿地概况")
    public JsonResult<Map<String, Object>> getSituationShow() {
        Map<String, Object> map = greLandLogic.getSituation();
        return JsonResult.ok(map);
    }

    @GetMapping(value = "/getParkSituation")
    @ApiOperation(value = "获取公园绿地概况")
    public JsonResult<Map<String, Object>> getParkSituation() {
        Map<String, Object> map = greLandLogic.getParkSituation();
        return JsonResult.ok(map);
    }

    @GetMapping(value = "/getParkSituationShow")
    @ApiOperation(value = "获取公园绿地概况")
    public JsonResult<Map<String, Object>> getParkSituationShow() {
        Map<String, Object> map = greLandLogic.getParkSituationShow();
        return JsonResult.ok(map);
    }

    @GetMapping(value = "/getAreaStat")
    @ApiOperation(value = "获取区域面积统计")
    public JsonResult<List<Map<String, Object>>> getAreaStat() {
        List<Map<String, Object>> map = greLandLogic.getAreaStat();
        return JsonResult.ok(map);
    }

    @PostMapping(value = "/getDataByBoundResource")
    @ApiOperation(value = "根据框选获取绿地率和绿地覆盖率")
    public JsonResult getDataByBoundResource(@RequestBody GreLandQuery greLandParam) {
        Map<String, Object> map = greLandLogic.getDataByBoundResource(greLandParam);
        return JsonResult.ok(map);
    }
}
